home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-04 / bipl.zip / PROGS.ZIP / PATCHU.ICN < prev    next >
Text File  |  1992-09-28  |  4KB  |  150 lines

  1. ############################################################################
  2. #
  3. #    File:     patchu.icn
  4. #
  5. #    Subject:  Program to implement UNIX-like patch
  6. #
  7. #    Author:   Rich Morin
  8. #
  9. #    Date:     June 18, 1990
  10. #
  11. ###########################################################################
  12. #
  13. #  This program reads a source file and a diff file, producing an
  14. #  updated file.  The diff file may be generated by the UNIX diff(1)
  15. #  utility, or by diffu.icn, which uses dif.icn for the hard work.
  16. #
  17. #  The original patch(1) utility, written by Larry Wall, is widely
  18. #  used in the UNIX community.
  19. #
  20. #  The diff file contains edit lines, separators, and text lines.
  21. #  Edit lines may take the forms:
  22. #
  23. #    #a#[,#]            <- add    lines
  24. #    #[,#]c#[,#]        <- change lines
  25. #    #[,#]d#            <- delete lines
  26. #
  27. #  Change lines contain only the string "---".  All other lines are
  28. #  text lines.  See diff(1) in any UNIX manual for more details.
  29. #
  30. ############################################################################
  31. #
  32. #  Requires:  co-expressions
  33. #
  34. ############################################################################
  35. #
  36. #  Links:  options, patch
  37. #
  38. ############################################################################
  39.  
  40. link options, patch
  41.  
  42. record diff_rec(pos, diffs)
  43.  
  44. global n1, n2, n3, n4
  45.  
  46. procedure main(arg)
  47.    local t, rev, source, dfile, diffs
  48.  
  49.   t := options(arg, "r")
  50.   rev := t["r"]
  51.  
  52.   if *arg ~= 2 then
  53.     zot("usage: patchu source diffs")
  54.  
  55.   source := open(arg[1]) | zot("cannot open " || arg[1])
  56.   dfile  := open(arg[2]) | zot("cannot open " || arg[2])
  57.  
  58. # every write(patch(source, get_diff(dfile))) # ? shouldn't need diffs ?
  59.  
  60.   diffs := []
  61.   every put(diffs, get_diff(dfile))
  62.   every write(patch(source, diffs, rev))
  63.  
  64. end
  65.  
  66.  
  67. procedure get_diff(dfile)        # get diff record
  68.   local ef, i1, i2, l1, l2, i, line
  69.  
  70.   repeat {
  71.     if ef := get_edit(dfile) then {
  72. #     write(">>> ",n1,", ",n2,", ",ef,", ",n3,", ",n4)
  73.       if ef == "a" then i1 := n1+1 else i1 := n1
  74.       if ef == "d" then i2 := n3+1 else i2 := n3
  75.       l1 := []
  76.       l2 := []
  77.       if ef == !"cd" then {
  78.         every i := n1 to n2 do {
  79.           line := !dfile | zot("unexpected end of edit data(1)")
  80.           if line[1:3] ~== "< " then
  81.             zot("bad edit data(1): " || line)
  82.           put(l1, line[3:0])
  83.         }
  84.       }
  85.  
  86.       if ef == "c" then {
  87.         line := !dfile | zot("unexpected end of edit data(2)")
  88.         if line ~== "---" then
  89.           zot("bad edit data(2): " || line)
  90.       }
  91.  
  92.       if ef == !"ac" then {
  93.         every i := n3 to n4 do {
  94.           line := !dfile | zot("unexpected end of edit data(3)")
  95.           if line[1:3] ~== "> " then
  96.             zot("bad edit data(3): " || line)
  97.           put(l2, line[3:0])
  98.         }
  99.       }
  100.       suspend [diff_rec(i1,l1), diff_rec(i2,l2)]
  101.     }
  102.     else
  103.       fail
  104.   }
  105.  
  106. end
  107.  
  108.  
  109. procedure get_edit(dfile)        # get edit parameters
  110.   local edit, i1, i2, ef, i3, i4
  111.  
  112.   edit := !dfile | fail
  113.   i1 := i2 := many(&digits, edit) | zot("bad edit spec(1): " || edit)
  114.   n1 := n2 := edit[1:i1]
  115.   if edit[i1] == "," then {
  116.     i2 := many(&digits, edit, i1+1) | zot("bad edit spec(2): " || edit)
  117.     n2 := edit[i1+1:i2]
  118.   }
  119.  
  120.   if edit[i2] == !"acd" then {
  121.     ef := edit[i2]
  122.     i3 := i4 := many(&digits, edit, i2+1) | zot("bad edit spec(3): " || edit)
  123.     n3 := n4 := edit[i2+1:i3]
  124.     if edit[i3] == "," then {
  125.       i4 := many(&digits, edit, i3+1) | zot("bad edit spec(4): " || edit)
  126.       n4 := edit[i3+1:i4]
  127.     }
  128.   }
  129.   else
  130.     zot("bad edit spec(5): " || edit)
  131.  
  132.   if i4 ~= *edit+1 then 
  133.     zot("bad edit spec(6): " || edit)
  134.  
  135.   if not 0 <= n3 <= n4 then
  136.     zot("bad edit spec(7): " || edit)
  137.  
  138.   if not 0 <= n1 <= n2 then
  139.     zot("bad edit spec(8): " || edit)
  140.  
  141.   return ef
  142.  
  143. end    
  144.  
  145.  
  146. procedure zot(msg)                # exit w/message
  147.   write(&errout, "patchu: " || msg)
  148.   exit(1)
  149. end
  150.